use super::*;
use copypasta::ClipboardProvider;
use eyre::Ok;
use fantoccini::{Client, ClientBuilder, Locator};
use once_cell::sync::Lazy;
use scraper::{Html, Selector};
// use

#[derive(Deserialize, Serialize)]
pub struct Training {
    pub training: Vec<String>,
}

async fn fetch_problem_with_client(problem: &str, client: &Client) -> eyre::Result<String> {
    let mut clipboard = copypasta::ClipboardContext::new().unwrap();

    client
        .goto(&format!("https://www.luogu.com.cn/problem/{}", problem))
        .await?;

    let detail = client
        .find(Locator::Css(include_str!("detail_selector")))
        .await?
        .text()
        .await?;

    let button = client.find(Locator::Css(include_str!("selector"))).await?;

    button.click().await?;

    let mut md = clipboard.get_contents().unwrap();

    md.insert_str(md.find("\n").unwrap() + 1, &detail);

    Ok(md)
}

pub async fn fetch_problem(problem: &str) -> eyre::Result<String> {
    let client = ClientBuilder::native()
        .connect("http://localhost:4444")
        .await?;

    fetch_problem_with_client(problem, &client).await
}

pub async fn fetch_problems<S: AsRef<str>>(
    problems: impl IntoIterator<Item = S>,
) -> eyre::Result<Vec<String>> {
    let mut ret = Vec::new();
    let client = ClientBuilder::native()
        .connect("http://localhost:4444")
        .await?;
    for p in problems {
        ret.push(fetch_problem_with_client(p.as_ref(), &client).await?);
    }
    Ok(ret)
}

pub async fn fetch_training(id: u32) -> eyre::Result<Vec<String>> {
    static TRAINING_SELECTOR: Lazy<Selector> =
        Lazy::new(|| Selector::parse("article li a").unwrap());

    let resp = reqwest::get(format!("https://www.luogu.com.cn/training/{}", id)).await?;
    let html = resp.text().await?;
    let html = Html::parse_document(&html);

    let res = html
        .select(&TRAINING_SELECTOR)
        .filter_map(|elm| elm.attr("href"))
        .map(|elm| {
            assert!(&elm[..9] == "/problem/");
            &elm[9..]
        })
        .map(String::from)
        .collect();

    Ok(res)
}

#[cfg(test)]
mod test {
    use super::*;

    #[tokio::test]
    async fn test_fetch() {
        let problem = "CF240F";
        let resp = reqwest::get(format!("https://www.luogu.com.cn/problem/{}", problem))
            .await
            .unwrap();
        let html = resp.text().await.unwrap();

        fs::write("tmp/.html", html).unwrap();

        let md = fetch_problem(problem).await.unwrap();
        fs::write("tmp/.md", md).unwrap();
    }

    #[tokio::test]
    async fn test_fetch_training() {
        let list = fetch_training(551).await.unwrap();
        dbg!(list);
    }
}
